import PackagesParser from './packages-parser';
import MethodsParser from './methods-parser';
import LifeCyclesParser from './life-cycles-parser';
import StateParser from './state-parser';
import PropsParser from './props-parser';
import ChildrenParser from './children-parser';
import type { INodeGenerator, NodeGeneratorProps, SourceCode } from '../types';

export default class NodeGenerator implements INodeGenerator {
  readonly schema: INodeGenerator['schema'];
  readonly packagesParser: INodeGenerator['packagesParser'];
  readonly methodsParser: INodeGenerator['methodsParser'];
  readonly lifeCyclesParser: INodeGenerator['lifeCyclesParser'];
  readonly stateParser: INodeGenerator['stateParser'];
  readonly propsParser: INodeGenerator['propsParser'];
  readonly childrenParser: INodeGenerator['childrenParser'];
  constructor(props: NodeGeneratorProps) {
    const { schema } = props;
    this.schema = schema;
    this.propsParser = new PropsParser({ schema });
    this.packagesParser = new PackagesParser({ schema });
    this.methodsParser = new MethodsParser({ schema });
    this.lifeCyclesParser = new LifeCyclesParser({
      schema,
      packagesParser: this.packagesParser,
    });
    this.stateParser = new StateParser({
      schema,
      packagesParser: this.packagesParser,
    });
    this.childrenParser = new ChildrenParser({ schema });
  }

  protected getComponentName(): SourceCode['componentName'] {
    return this.schema.componentName;
  }

  protected getExport(): SourceCode['export'] {
    return true;
  }

  async compiler(): Promise<SourceCode> {
    const children = await this.childrenParser.parse();
    const props = await this.propsParser.parse();
    const state = await this.stateParser.parse();
    const methods = await this.methodsParser.parse();
    const lifeCycles = await this.lifeCyclesParser.parse();
    const sourceCode: SourceCode = {
      export: true,
      componentName: this.getComponentName(),
      imports: this.packagesParser.toString(),
    };
    if (children) sourceCode.children = children;
    if (props) sourceCode.props = props;
    if (state) sourceCode.state = state;
    if (methods) sourceCode.methods = methods;
    if (lifeCycles) sourceCode.lifeCycles = lifeCycles;
    return sourceCode;
  }
}
